#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFileDialog>
#include <QUrl>

unsigned char cep4_palette_raw_data[] =
{
0xff, 0xff, 0xff, 0x00, 0xcc, 0xff, 0xff, 0x00, 0x99, 0xff, 0xff, 0x00,
0x66, 0xff, 0xff, 0x00, 0x33, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
0xff, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x99, 0xcc, 0xff, 0x00,
0x66, 0xcc, 0xff, 0x00, 0x33, 0xcc, 0xff, 0x00, 0x00, 0xcc, 0xff, 0x00,
0xff, 0x99, 0xff, 0x00, 0xcc, 0x99, 0xff, 0x00, 0x99, 0x99, 0xff, 0x00,
0x66, 0x99, 0xff, 0x00, 0x33, 0x99, 0xff, 0x00, 0x00, 0x99, 0xff, 0x00,
0xff, 0x66, 0xff, 0x00, 0xcc, 0x66, 0xff, 0x00, 0x99, 0x66, 0xff, 0x00,
0x66, 0x66, 0xff, 0x00, 0x33, 0x66, 0xff, 0x00, 0x00, 0x66, 0xff, 0x00,
0xff, 0x33, 0xff, 0x00, 0xcc, 0x33, 0xff, 0x00, 0x99, 0x33, 0xff, 0x00,
0x66, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x00, 0x33, 0xff, 0x00,
0xff, 0x00, 0xff, 0x00, 0xcc, 0x00, 0xff, 0x00, 0x99, 0x00, 0xff, 0x00,
0x66, 0x00, 0xff, 0x00, 0x33, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0xff, 0xcc, 0x00, 0xcc, 0xff, 0xcc, 0x00, 0x99, 0xff, 0xcc, 0x00,
0x66, 0xff, 0xcc, 0x00, 0x33, 0xff, 0xcc, 0x00, 0x00, 0xff, 0xcc, 0x00,
0xff, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x00, 0x99, 0xcc, 0xcc, 0x00,
0x66, 0xcc, 0xcc, 0x00, 0x33, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00,
0xff, 0x99, 0xcc, 0x00, 0xcc, 0x99, 0xcc, 0x00, 0x99, 0x99, 0xcc, 0x00,
0x66, 0x99, 0xcc, 0x00, 0x33, 0x99, 0xcc, 0x00, 0x00, 0x99, 0xcc, 0x00,
0xff, 0x66, 0xcc, 0x00, 0xcc, 0x66, 0xcc, 0x00, 0x99, 0x66, 0xcc, 0x00,
0x66, 0x66, 0xcc, 0x00, 0x33, 0x66, 0xcc, 0x00, 0x00, 0x66, 0xcc, 0x00,
0xff, 0x33, 0xcc, 0x00, 0xcc, 0x33, 0xcc, 0x00, 0x99, 0x33, 0xcc, 0x00,
0x66, 0x33, 0xcc, 0x00, 0x33, 0x33, 0xcc, 0x00, 0x00, 0x33, 0xcc, 0x00,
0xff, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x99, 0x00, 0xcc, 0x00,
0x66, 0x00, 0xcc, 0x00, 0x33, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc, 0x00,
0xff, 0xff, 0x99, 0x00, 0xcc, 0xff, 0x99, 0x00, 0x99, 0xff, 0x99, 0x00,
0x66, 0xff, 0x99, 0x00, 0x33, 0xff, 0x99, 0x00, 0x00, 0xff, 0x99, 0x00,
0xff, 0xcc, 0x99, 0x00, 0xcc, 0xcc, 0x99, 0x00, 0x99, 0xcc, 0x99, 0x00,
0x66, 0xcc, 0x99, 0x00, 0x33, 0xcc, 0x99, 0x00, 0x00, 0xcc, 0x99, 0x00,
0xff, 0x99, 0x99, 0x00, 0xcc, 0x99, 0x99, 0x00, 0x99, 0x99, 0x99, 0x00,
0x66, 0x99, 0x99, 0x00, 0x33, 0x99, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00,
0xff, 0x66, 0x99, 0x00, 0xcc, 0x66, 0x99, 0x00, 0x99, 0x66, 0x99, 0x00,
0x66, 0x66, 0x99, 0x00, 0x33, 0x66, 0x99, 0x00, 0x00, 0x66, 0x99, 0x00,
0xff, 0x33, 0x99, 0x00, 0xcc, 0x33, 0x99, 0x00, 0x99, 0x33, 0x99, 0x00,
0x66, 0x33, 0x99, 0x00, 0x33, 0x33, 0x99, 0x00, 0x00, 0x33, 0x99, 0x00,
0xff, 0x00, 0x99, 0x00, 0xcc, 0x00, 0x99, 0x00, 0x99, 0x00, 0x99, 0x00,
0x66, 0x00, 0x99, 0x00, 0x33, 0x00, 0x99, 0x00, 0x00, 0x00, 0x99, 0x00,
0xff, 0xff, 0x66, 0x00, 0xcc, 0xff, 0x66, 0x00, 0x99, 0xff, 0x66, 0x00,
0x66, 0xff, 0x66, 0x00, 0x33, 0xff, 0x66, 0x00, 0x00, 0xff, 0x66, 0x00,
0xff, 0xcc, 0x66, 0x00, 0xcc, 0xcc, 0x66, 0x00, 0x99, 0xcc, 0x66, 0x00,
0x66, 0xcc, 0x66, 0x00, 0x33, 0xcc, 0x66, 0x00, 0x00, 0xcc, 0x66, 0x00,
0xff, 0x99, 0x66, 0x00, 0xcc, 0x99, 0x66, 0x00, 0x99, 0x99, 0x66, 0x00,
0x66, 0x99, 0x66, 0x00, 0x33, 0x99, 0x66, 0x00, 0x00, 0x99, 0x66, 0x00,
0xff, 0x66, 0x66, 0x00, 0xcc, 0x66, 0x66, 0x00, 0x99, 0x66, 0x66, 0x00,
0x66, 0x66, 0x66, 0x00, 0x33, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00,
0xff, 0x33, 0x66, 0x00, 0xcc, 0x33, 0x66, 0x00, 0x99, 0x33, 0x66, 0x00,
0x66, 0x33, 0x66, 0x00, 0x33, 0x33, 0x66, 0x00, 0x00, 0x33, 0x66, 0x00,
0xff, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x66, 0x00, 0x99, 0x00, 0x66, 0x00,
0x66, 0x00, 0x66, 0x00, 0x33, 0x00, 0x66, 0x00, 0x00, 0x00, 0x66, 0x00,
0xff, 0xff, 0x33, 0x00, 0xcc, 0xff, 0x33, 0x00, 0x99, 0xff, 0x33, 0x00,
0x66, 0xff, 0x33, 0x00, 0x33, 0xff, 0x33, 0x00, 0x00, 0xff, 0x33, 0x00,
0xff, 0xcc, 0x33, 0x00, 0xcc, 0xcc, 0x33, 0x00, 0x99, 0xcc, 0x33, 0x00,
0x66, 0xcc, 0x33, 0x00, 0x33, 0xcc, 0x33, 0x00, 0x00, 0xcc, 0x33, 0x00,
0xff, 0x99, 0x33, 0x00, 0xcc, 0x99, 0x33, 0x00, 0x99, 0x99, 0x33, 0x00,
0x66, 0x99, 0x33, 0x00, 0x33, 0x99, 0x33, 0x00, 0x00, 0x99, 0x33, 0x00,
0xff, 0x66, 0x33, 0x00, 0xcc, 0x66, 0x33, 0x00, 0x99, 0x66, 0x33, 0x00,
0x66, 0x66, 0x33, 0x00, 0x33, 0x66, 0x33, 0x00, 0x00, 0x66, 0x33, 0x00,
0xff, 0x33, 0x33, 0x00, 0xcc, 0x33, 0x33, 0x00, 0x99, 0x33, 0x33, 0x00,
0x66, 0x33, 0x33, 0x00, 0x33, 0x33, 0x33, 0x00, 0x00, 0x33, 0x33, 0x00,
0xff, 0x00, 0x33, 0x00, 0xcc, 0x00, 0x33, 0x00, 0x99, 0x00, 0x33, 0x00,
0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
0xff, 0xff, 0x00, 0x00, 0xcc, 0xff, 0x00, 0x00, 0x99, 0xff, 0x00, 0x00,
0x66, 0xff, 0x00, 0x00, 0x33, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0xff, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x99, 0xcc, 0x00, 0x00,
0x66, 0xcc, 0x00, 0x00, 0x33, 0xcc, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00,
0xff, 0x99, 0x00, 0x00, 0xcc, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,
0x66, 0x99, 0x00, 0x00, 0x33, 0x99, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00,
0xff, 0x66, 0x00, 0x00, 0xcc, 0x66, 0x00, 0x00, 0x99, 0x66, 0x00, 0x00,
0x66, 0x66, 0x00, 0x00, 0x33, 0x66, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,
0xff, 0x33, 0x00, 0x00, 0xcc, 0x33, 0x00, 0x00, 0x99, 0x33, 0x00, 0x00,
0x66, 0x33, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00,
0x66, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00,
0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xaa, 0x00,
0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x55, 0x00,
0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x11, 0x00,
0x00, 0xee, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00,
0x00, 0xaa, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x55, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
0x00, 0x11, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00,
0xbb, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
0x77, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
0x22, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0x00,
0xdd, 0xdd, 0xdd, 0x00, 0xbb, 0xbb, 0xbb, 0x00, 0xaa, 0xaa, 0xaa, 0x00,
0x88, 0x88, 0x88, 0x00, 0x77, 0x77, 0x77, 0x00, 0x55, 0x55, 0x55, 0x00,
0x44, 0x44, 0x44, 0x00, 0x22, 0x22, 0x22, 0x00, 0x11, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00
};


MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow)
{
	ui->setupUi(this);

	setAcceptDrops(true);

	for ( int i = 0 ; i < 256; ++i)
	{
		m_colorTable.append(qRgb( cep4_palette_raw_data[i*4 +2], cep4_palette_raw_data[i*4 +1], cep4_palette_raw_data[i*4 + 0]));
	}
}

MainWindow::~MainWindow()
{
	delete ui;
}

void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
	if ( e->mimeData()->hasUrls() )
	{
		e->acceptProposedAction();
	}
}

void MainWindow::dropEvent(QDropEvent *e)
{
	foreach ( const QUrl &url, e->mimeData()->urls())
	{
		QString fileName = url.toLocalFile();
		qDebug("[%s] drop %s", Q_FUNC_INFO, qPrintable(fileName));
		convertScreenShot(fileName);
	}
}

void MainWindow::on_actionExit_triggered()
{
	qDebug("[%s]", Q_FUNC_INFO);
	close();
}


union _crc {
		unsigned char b[2];
		unsigned short w;
};

/// ccit crc 계산 (crc 16)
/// big-endian/little-endian 구분 필요
/// \param start_crc
/// \param p
/// \param len
/// \return crc
static unsigned short ccit_crc(unsigned start_crc, unsigned char *p, int len)
{
		union _crc crc;
		int i;
		crc.w = start_crc;

		while(len-- > 0) {
				//crc.b[0] ^= *p++; // for big-endian
				crc.b[1] ^= *p++; // for little-endian
				for (i = 0; i < 8; ++i) {
						if (crc.w & 0x8000) {
								crc.w <<= 1;
								crc.w ^= 0x01021;
						} else {
								crc.w <<= 1;
						}
				}
		}
		return (crc.w);
}

int MainWindow::readDumpTextFile(const QString &filePath, QList<QByteArray> & dumpList)
{

	// read file contents
	QFile file(filePath);
	if ( ! file.open(QFile::ReadOnly) )
	{
		qDebug("[%s] open error [%s].", Q_FUNC_INFO, qPrintable(filePath));
		return 0;

	}
	QByteArray data = file.readAll();
	file.close();




	dumpList.clear();

	int nextIdx = 0;
	while ( 1 )
	{
		int startIdx = data.indexOf("CPE-4000 screen hex start", nextIdx);
		if ( startIdx >= 0 )
		{
			int endIdx = data.indexOf("CPE-4000 screen hex end", startIdx);
			if ( endIdx > startIdx )
			{
				dumpList.append(data.mid(startIdx, endIdx - startIdx));
				nextIdx = endIdx + 25;
			}
			else
				break;
		}
		else
			break;
	}

	return dumpList.size();
}

QByteArray MainWindow::textDumpToBin(const QByteArray &src)
{
	QByteArray tmp = src;

	int crcIdx = src.lastIndexOf("CRC ");
	QString crcStr = src.mid( crcIdx ).trimmed();
	crcStr.remove("CRC");
	int crcVal = crcStr.trimmed().toInt();

	tmp.remove(crcIdx, 100);

	qDebug("[%s] CRC = %d", Q_FUNC_INFO, crcVal);


	int startIdx = tmp.indexOf("HEX");
	tmp.remove(0, startIdx + 3);
	tmp.replace(" ", "");
	tmp.replace("\r", "");
	tmp.replace("\n", "");

	QByteArray bin = QByteArray::fromHex(tmp);

	int calcVal = ccit_crc(0, (unsigned char *)bin.constData(), bin.size());
	if ( crcVal == calcVal )
		return bin;

	return QByteArray();
}

void MainWindow::convertScreenShot(const QString & filePath)
{
	QList <QByteArray> hexList;
	readDumpTextFile(filePath, hexList);

	if ( hexList.size()  == 0 )
	{
		qDebug("[%s] hex dump not found", Q_FUNC_INFO);
		return;
	}

	qDebug("[%s] %d hex dumps found", Q_FUNC_INFO, hexList.size());


	for (int i = 0 ; i < hexList.size(); ++i )
	{
		QByteArray bin = textDumpToBin(hexList[i]);

		if ( !bin.isEmpty())
		{
			QImage img(800, 600, QImage::Format_Indexed8);
			img.setColorTable(m_colorTable);

			::memcpy(img.bits(), bin.constData(), bin.size());

			QImage sc = img.mirrored(true, true);
			ui->label->setPixmap(QPixmap::fromImage(sc));

			QString imgPath;
			imgPath.sprintf("%s_%04d.png", qPrintable(filePath), i);
			sc.save( imgPath);
		}
	}
}

void MainWindow::on_actionOpen_triggered()
{
	qDebug("[%s]", Q_FUNC_INFO);


	// select file
	QString filePath = QFileDialog::getOpenFileName(this, "Open Dump File", m_prevFile, "Dump files (*.txt);;All files (*.*)");

	if ( filePath.isEmpty() )
	{
			qDebug("[%s] no file selected. canceled.", Q_FUNC_INFO);
			return;
	}
	qDebug("[%s] open %s.", Q_FUNC_INFO, qPrintable(filePath));

	convertScreenShot(filePath);

}

